#!/usr/bin/env python3
# filename: models.py

from flask_sqlalchemy import SQLAlchemy
from flask_login import AnonymousUserMixin
from hzsaiblog.extensions import bcrypt

import datetime

# init the db object in /hzsaiblog/__init__.py again
db = SQLAlchemy()


posts_tag = db.Table(
        'posts_tag',
        db.Column('post_id', db.String(64), db.ForeignKey('posts.id')),
        db.Column('tag_id', db.String(64), db.ForeignKey('tags.id')))

users_roles = db.Table(
        'users_roles',
        db.Column('role_id', db.String(64), db.ForeignKey('roles.id')),
        db.Column('user_id', db.String(64), db.ForeignKey('users.id')))


class User(db.Model):
    """Represents Proected users."""

    # set table name
    __tablename__ = 'users'
    id = db.Column(db.String(64), primary_key=True)
    username = db.Column(db.String(127), nullable=False)
    password = db.Column(db.String(127), nullable=False)
    motto = db.Column(db.String(1024))
    lastseen = db.Column(db.DATETIME)
    register_t = db.Column(db.DATETIME)
    auth_type = db.Column(db.Integer)
    # Establish contact with Post's ForeignKey
    posts = db.relationship(
            'Post',
            backref='users',
            lazy='dynamic')

    roles = db.relationship(
            'Role',
            secondary=users_roles,
            backref=db.backref('users', lazy='dynamic'))

    def __init__(self, id, username, password):
        self.id = id
        self.username = username
        self.password = self.set_password(password)
        self.auth_type = 0x00

        default = Role.query.filter_by(name="default").one()
        self.roles.append(default)

    def __repr__(self):
        """Define the string format for instance of User"""
        return "<Model User `{0}`>".format(self.username)

    def set_password(self, password):
        """Convert the password to cryptograph via flask-bcrypt"""
        return bcrypt.generate_password_hash(password)

    def check_password(self, password):
        return bcrypt.check_password_hash(self.password, password)

    def is_authenticated(self):
        """check the user whether logged in."""

        if isinstance(self, AnonymousUserMixin):
            return False
        else:
            return True

    def is_active():
        """Check the user whether pass the activation process."""
        return True

    def is_anonymous(self):
        """Check the user's login status whether is anonymous."""

        if isinstance(self, AnonymousUserMixin):
            return True
        else:
            return False

    def get_id(self):
        """get user uuid"""

        return self.id


class Role(db.Model):
    """Represtents Role of user."""
    __tablename__ = 'roles'

    id = db.Column(db.String(64), primary_key=True)
    name = db.Column(db.String(127), unique=True)
    description = db.Column(db.String(127))

    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __repr__(self):
        return "<Model Role `{0}`>".format(self.name)


class Post(db.Model):
    """Represents Proected posts."""

    __tablename__ = 'posts'
    id = db.Column(db.String(64), primary_key=True)
    title = db.Column(db.String(127))
    text = db.Column(db.Text())
    publish_date = db.Column(db.DateTime)
    latest_tag = db.Column(db.String(64))
    # Set the foreign key for Post
    user_id = db.Column(db.String(64), db.ForeignKey('users.id'))
    comment = db.relationship(
            'Comment',
            backref='posts',
            lazy='dynamic')

    tags = db.relationship(
            'Tag',
            secondary=posts_tag,
            backref=db.backref('posts', lazy='dynamic'))

    def __init__(self, id, title):
        self.id = id
        self.title = title

    def __repr__(self):
        return "Model Post `{0}`".format(self.title)


class Comment(db.Model):
    """Represents Protected comments."""

    __tablename__ = 'comments'
    id = db.Column(db.String(64), primary_key=True)
    name = db.Column(db.String(127))
    text = db.Column(db.Text())
    date = db.Column(db.DateTime())
    post_id = db.Column(db.String(64), db.ForeignKey('posts.id'))

    def __init__(self, id,  name, text="", date=datetime.datetime.now()):
        self.id = id
        self.name = name
        # self.text = text
        # self.date = date

    def __repr__(self):
        return "<Model Comment `{0}>".format(self.name)


class Tag(db.Model):
    """Represents Proected tags."""

    __tablename__ = 'tags'
    id = db.Column(db.String(64), primary_key=True)
    name = db.Column(db.String(127))

    def __init__(self, id, name):
        self.id = id
        self.name = name

    def __repr__(self):
        return "<Model Tag `{0}`>".format(self.name)
